package com.itjiange.socket;

import com.itjiange.model.pojo.FileSocket;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;

import static com.itjiange.constant.FileStatusConstant.*;

/**
 * ServerSocket 接收请求
 *
 * @author ItJiange
 * @date 2023/11/03
 */
@Slf4j
public class SocketReceive {

    private String rootPath;

    private Socket socket;

    public SocketReceive(Socket socket, String rootPath) {
        this.socket = socket;
        this.rootPath = rootPath;
    }

    /**
     * 接收 socket 请求
     */
    public void receiveService() {
        if (socket == null) {
            log.error("连接失败...");
            return;
        }
        log.info("连接客户端 IP 地址：{} ", socket.getInetAddress().getHostAddress());
        // 获取文件传输信息
        FileSocket fileSocket = getFileSocket();
        String serverPath = rootPath + File.separator + fileSocket.getFileName();
        // 根据文件状态响应对应的操作
        operateFileByStatus(fileSocket.getFileState(), fileSocket.getFileByteInfo(), serverPath);
        // 关闭流
        try {
            socket.close();
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }

    /**
     * 对文件执行不同的操作
     * @param fileState
     */
    private void operateFileByStatus(String fileState, byte[] fileByteInfo, String serverPath) {
        switch (fileState) {
            case FILE_DELETE -> deleteFileObj(serverPath);
            case FILE_CHANGE -> operationObj(serverPath, fileByteInfo);
            case FILE_CREATE -> operationObj(serverPath, fileByteInfo);
        }
    }

    /**
     * 在服务端创建或修改文件
     * @param serverPath
     * @param fileByteInfo
     */
    private void operationObj(String serverPath, byte[] fileByteInfo) {
        File file = new File(serverPath);
        // 当文件夹不存在时，创建文件夹
        if (file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try (ByteArrayInputStream fileInfoIn = new ByteArrayInputStream(fileByteInfo);
            FileOutputStream fileInfoOut = new FileOutputStream(serverPath)) {
            fileInfoIn.transferTo(fileInfoOut);
        } catch (IOException e) {
            log.info(e.getMessage());
        }
    }

    /**
     * 删除服务端文件
     * @param serverPath
     */
    private void deleteFileObj(String serverPath) {
        // 获取 file 对象
        File file = new File(serverPath);
        // 判断文件是否存在
        if (!file.exists()) {
            log.info("该文件不存在！{}", serverPath);
            return;
        }
        // 判断文件是否删除成功
        if (file.delete()) {
            log.info("文件删除成功！{}", serverPath);
        } else {
            log.info("文件删除失败！");
        }
    }

    /**
     * 获取文件对象
     *
     * @return
     */
    private FileSocket getFileSocket() {
        // 创建 fileSocket 对象
        FileSocket fileSocket = new FileSocket();
        InputStream socketInputStream = null;
        try {
            socketInputStream = socket.getInputStream();
        } catch (IOException e) {
            log.info(e.getMessage());
        }
        // 通过 socket 接收文件信息
        String fileState = receiveFileState(socketInputStream);
        String fileName = receiveFileName(socketInputStream, fileState);
        byte[] fileByteInfo = receiveFileInfo(socketInputStream);
        // 参数映射至 fileSocket
        fileSocket.setFileState(fileState);
        fileSocket.setFileName(fileName);
        fileSocket.setFileByteInfo(fileByteInfo);
        // 返回 fileSocket 对象
        return fileSocket;
    }

    /**
     * 接收文件状态
     *
     * @return
     */
    private String receiveFileState(InputStream socketInputStream) {
        String fileState = "";
        try {
            DataInputStream fileNameIn = new DataInputStream(socketInputStream);
            // 获取文件信息
            fileState = fileNameIn.readUTF();
            log.info(fileState);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return fileState;
    }

    /**
     * 接收文件名
     *
     * @return
     */
    private String receiveFileName(InputStream socketInputStream, String fileState) {
        String fileName = "";
        try {
            DataInputStream fileNameIn = new DataInputStream(socketInputStream);
            // 获取文件信息
            fileName = fileNameIn.readUTF();
            logPrint(fileState, fileName);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return fileName;
    }

    /**
     * 文件子节信息
     *
     * @return
     */
    private byte[] receiveFileInfo(InputStream socketInputStream) {
        byte[] fileByteInfo = new byte[0];
        try {
            DataInputStream fileCodeInfoIn = new DataInputStream(socketInputStream);
            // 获取文件信息
            fileByteInfo = fileCodeInfoIn.readAllBytes();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return fileByteInfo;
    }

    /**
     * 输出日志信息
     *
     * @param fileStatus
     * @param fileName
     */
    private void logPrint(String fileStatus, String fileName) {
        if (FILE_CHANGE.equals(fileStatus)) {
            log.info("修改文件: {} 成功", fileName);
        } else if (FILE_CREATE.equals(fileStatus)) {
            log.info("创建文件: {} 成功", fileName);
        } else if (FILE_DELETE.equals(fileStatus)) {
            log.info("删除文件: {} 成功", fileName);
        }
    }

    /**
     * 写入文件内容
     *
     * @param fileName
     * @param fileMessage
     */
//    private static void writeFileMessage(String fileName, byte[] fileMessage) {
//        String context = ProfileUtils.getContext();
//        try (FileOutputStream fos = new FileOutputStream(context + File.separator + fileName);) {
//            fos.write(fileMessage);
//        } catch (IOException e) {
//            log.debug(e.getMessage());
//        }
//    }


    /**
     * 操作文件
     *
     * @param fileInfo
     */
//    private void operateFileByStatus(FileInfo fileInfo) {
//        String fileName = fileInfo.getFileName();
//        String fileStatus = fileInfo.getFileStatus();
//        byte[] fileMessage = fileInfo.getFileMessage();
//
//        if (!FileStatusConstants.FILE_DELETE.equals(fileStatus)) {
//            writeFileMessage(fileName, fileMessage);
//            log.info("{}成功！{} : {}", fileStatus, fileStatus, fileName);
//        } else {
//            deleteFile(fileName);
//        }

//    }
    /**
     * 删除文件
     *
     * @param fileName
     */
//    private static void deleteFile(String fileName) {
//        String context = ProfileUtils.getContext();
//        File file = new File(context + File.separator + fileName);
//        if (file.delete()) {
//            log.info("删除文件成功，文件名 : {}", fileName);
//        } else {
//            log.info("删除失败");
//        }

//    }
}
